from datetime import datetime
from queue import Queue
import threading

from pandas import DataFrame

from api.api_db import get_loc_unique_list
from common.pd import get_tb_data, DF_Table, get_df_col_value_df, get_cols_values_dict, get_col_values
from common.playwright_driver import WebDriver
from common.utils import get_day_differ, datetime_str_to_datetime, timeit
from common.utils import get_today_str, get_now_str
from common.mydb import Table
from common.singleton import singleton
from common.config import Public_Data, get_project_name, Sender_Str, DRCS_Overall_View, WebDriver_DDL_Path
from project.idrs import idrs_flow

from project.web_comm import get_token_to_public_data
from project.once import get_once_json, dic_to_fax, dic_to_doc
from project.file import download_file_to_save

public_data = Public_Data()


# region  多线程处理文函信息的获取和存入数据库

def get_file_to_db(contract):
    project = contract[1]
    channel_code = contract[2]
    page_index = 1
    unfinished = True
    while unfinished:
        # 获取文件json
        text_json = get_once_json(project, channel_code, index_page=page_index)
        if text_json:
            file_json = text_json['resultList']
            file_json_dict = {"contract": contract, "file_dic": file_json}
            file_dic = classify_file_dic(file_json_dict)  # 处理file_json
            file_dic_to_db(file_dic)  # 将文件信息存入数据库

            if text_json["recordCount"] <= 1000 * page_index:
                unfinished = False
            else:
                page_index += 1
    return f"已完成{project}-{channel_code}的文函更新"


# 将处理后的文件信息存入数据库
def file_dic_to_db(data_dic) -> None:
    """
    将转化的文函字典列表传送至数据库
    data_dic :{"faxes": fax_list, "doc_e": doc_e_list, "doc_f": doc_f_list}
    """
    fax_tb = DF_Table("fax")
    doc_e_tb = DF_Table("doc_e")
    doc_f_tb = DF_Table("doc")
    try:
        doc_f_list = data_dic["doc_f"]
        fax_list = data_dic["faxes"]
        doc_e_list = data_dic["doc_e"]
        if doc_e_list:
            doc_e_tb.file_dict_list_to_table(doc_e_list)
        if doc_f_list:
            doc_f_tb.file_dict_list_to_table(doc_f_list)
        if fax_list:
            fax_tb.file_dict_list_to_table(fax_list)
    except Exception as e:
        print(e)


# 通过页面获取文函信息

# endregion


# 合同数据表


# 文件更新日期数据表的查询与
@singleton
class Tb_Message(Table):
    def __init__(self):
        super().__init__("message")
        self.col_list = ["id", "ms_name", "ms_date", "ms_value"]
        self.update_col_list = ["ms_value"]
        self.key_col = "ms_name"

    def get_data(self, ms_name):
        return self.find_one(f" ms_name='{ms_name}'")

    def update_tb_message(self, ms_name, ms_value):
        data = self.get_data(ms_name)
        if data:
            self.update_one_col("ms_value", ms_value, f" ms_name='{ms_name}'")
        else:
            ms_date = get_now_str()
            self.insert_row([ms_name, ms_date, ms_value])

    def get_update_file_date(self):
        data = self.get_data('update_file')
        if data:
            print(data)
            return data[3]

    def update_file_date(self):
        update_date = get_today_str()
        self.update_tb_message("file_update", update_date)


# region 合同相关信息功能
def get_contract_by_lot_code(lot_code_str):
    """
    通过采购包信息获取合同信息
    """
    return get_tb_data("contract", f"lot_code like '%{lot_code_str}%'")


# endregion

# region 文函处理

# 将文函信息存到数据库
def file_data_to_db() -> str:
    """
    将转化的文函字典列表传送至数据库
    data_dic :{"faxes": fax_list, "doc_e": doc_e_list, "doc_f": doc_f_list}
    """
    public_data = Public_Data()
    fax_tb = DF_Table("fax")
    doc_e_tb = DF_Table("doc_e")
    doc_f_tb = DF_Table("doc")
    if public_data.update_all:
        fax_tb.clear_data()
        doc_f_tb.clear_data()
        doc_e_tb.clear_data()
    i = 0
    while True:
        file_queue = public_data.file_dic_list_queue
        data_dic = file_queue.get()
        if file_queue == "end":
            print("已更新完成")
            return "已更新完成"
        file_dic_to_db(data_dic)


# 将文函信息进行处理为数据表字典，并放入public_data.file_dic_list_queue
def file_json_to_queue():
    """将文函信息进行处理为数据表字典，并放入public_data.file_dic_list_queue"""
    while True:
        json_queue: Queue = public_data.file_json_queue
        result = "更新关闭"
        json_dic = json_queue.get()
        if json_dic == "end":
            return result

        data = classify_file_dic(json_dic)
        public_data.file_dic_list_queue.put(data)


def classify_file_dic(json_dic: dict) -> dict:
    """
    将文函信息进行处理为数据表字典，
    返回值 {"faxes": fax_list, "doc_e": doc_e_list, "doc_f": doc_f_list}
    """

    contract: list = json_dic["contract"]
    file_dices = json_dic["file_dic"]
    doc_f_list = []
    fax_list = []
    doc_e_list = []
    for file_dic in file_dices:
        if 'LETTERS' in file_dic["category"]:
            fax_list.append(dic_to_fax(file_dic, contract))
        elif 'TECHDOCS' in file_dic["category"]:
            doc = dic_to_doc(file_dic, contract)
            if doc["doc_type"] == "doc_e":
                doc_e_list.append(doc["doc"])
            else:
                doc_f_list.append(doc["doc"])
    return {"faxes": fax_list, "doc_e": doc_e_list, "doc_f": doc_f_list}


# endregion


@timeit
def update_contracts_file():
    """
    采用多线程获取once中合同的文函信息放入 public_data.file_json_queue 中
    文函信息格式：{"contract": contract, "file_dic": file_dices}
    更新完成后，发送字符串 "end"
    """
    public_data = Public_Data()
    df_contract = public_data.Df_Contract
    if df_contract.empty:  # 检查是否有合同信息
        return "无合同信息"
    if not public_data.Token:  # 检查是否有Token
        get_token_to_public_data()
        if not public_data.Token:
            return "获取身份验证信息不成功"
    # period = __get_period()  # 获取需要更新的周期
    contract_list = df_contract[["id", "project", "channel_code", "lot_code", "factory", "author_code"]].values.tolist()
    threads = [threading.Thread(target=get_one_file, args=(contract,)) for contract in contract_list]
    for thread in threads:
        thread.start()
    thread_file_to_queue = threading.Thread(target=file_json_to_queue)  # 将处理的文件信息放入队列
    thread_file_to_queue.start()
    thread_file_to_db = threading.Thread(target=file_data_to_db)  # 将处理的文件信息放入队列
    thread_file_to_db.start()
    file_data_to_db()
    # 等待子程序结束
    for thread in threads:
        thread.join()
    print("获取网络文件完成")
    queue: Queue = public_data.file_json_queue
    queue.put("end")
    thread_file_to_queue.join()
    # 给两个队列传送结束标志字符串

    file_queue = public_data.file_dic_list_queue
    file_queue.put("end")
    print("文函分类处理完成")
    thread_file_to_db.join()
    print("文件存储数据库完成")


# 获取一个合同的文函信息
def get_one_file(contract):
    """
    para: contract 格式 ["id","project","channel_code"]
    根据合同信息获取合同的文函信息
    文函信息格式：{"contract": contract, "file_dic": file_dices}
    """
    public_data = Public_Data()
    project = contract[1]
    channel_code = contract[2]
    page_index = 1
    unfinished = True
    while unfinished:
        text_json = get_once_json(project, channel_code, index_page=page_index)
        if text_json:
            file_dices = text_json['resultList']
            queue: Queue = public_data.file_json_queue
            queue.put({"contract": contract, "file_dic": file_dices})
            if text_json["recordCount"] <= 1000 * page_index:
                unfinished = False
            else:
                page_index += 1


# region 处理 更新周期
def __get_update_differ_days():
    tb_message = Tb_Message()
    last_update_day_str = tb_message.get_update_file_date()
    # print(last_update_day_str)
    last_update_time = datetime_str_to_datetime(last_update_day_str)
    # print(last_update_day)
    return get_day_differ(last_update_time, datetime.now()) + 1


def __get_period():
    """
    计算本次查询的时间差
    period: [-week,  -month,  -quarter 三个月,  -halfyear, -year]
    """
    date_diff = __get_update_differ_days()
    print(date_diff)
    if date_diff < 7:
        period = "-week"
    if 7 < date_diff <= 30:
        period = "-month"
    elif 30 < date_diff <= 120:
        period = " -quarter"
    elif 120 < date_diff <= 180:
        period = " -halfyear"
    elif 180 < date_diff <= 365:
        period = " -year"
    else:
        period = ""
    return period


# endregion


# region 和视图层的接口

# 获取合同信息
def get_contract_df(condition=None) -> DataFrame:
    """获取数据库中的合同信息"""

    return get_tb_data("contract", condition)


def get_refer_contract_df(condition=None) -> DataFrame:
    public_data.Df_Contract = get_contract_df()
    return get_tb_data("refer_contract", condition)


# endregion
def get_attachment_list(attachment_str):
    if attachment_str:
        sys_attachment_list = attachment_str.split(",")
        if "，" in attachment_str:
            att_list = []
            for sys_att in sys_attachment_list:
                sup_list = sys_att.split("，")
                att_list.extend(sup_list)
            return att_list
        return sys_attachment_list


def create_drcs_dict(df_data: DataFrame):
    """把文件信息转为DRCS"""
    df_new_drcs = get_df_col_value_df(df_data, "status", 0)
    drcs_id_list = get_loc_unique_list(df_new_drcs, "drcs_id")
    drcs_dict_list = []
    for drcs_id in drcs_id_list:
        df_drcs_info = get_df_col_value_df(df_new_drcs, "drcs_id", drcs_id)
        drcs_col_name_list = ["drcs_id", "prj_code", "lot_code", "receiver_code", "checker", "approver", "title", "cc",
                              "sys_attachment",
                              "doc_channel", "overall_view"]
        df_drcs: DataFrame = df_drcs_info.loc[:, drcs_col_name_list]
        drcs_dict: dict = df_drcs.iloc[0].to_dict()
        drcs_dict["prj_name"] = get_project_name(drcs_dict["prj_code"])
        drcs_dict["checker_code"] = drcs_dict["checker"][:7]
        drcs_dict["approver_code"] = drcs_dict["approver"][:7]
        drcs_dict["sender_str"] = Sender_Str
        drcs_dict["sys_attachment"] = get_attachment_list(drcs_dict["sys_attachment"])

        if not drcs_dict["overall_view"]:
            drcs_dict["overall_view"] = DRCS_Overall_View

        doc_col_name = ["doc_code", "review_result", "doc_review"]
        df_doc_info: DataFrame = df_drcs_info.loc[:, doc_col_name]
        doc_dict = df_doc_info.to_dict("list")
        drcs_dict.update(doc_dict)
        drcs_dict_list.append(drcs_dict)

    return drcs_dict_list


def create_drcs_flow(drcs_dict_list, observer=None):
    if drcs_dict_list:
        for drcs_dict in drcs_dict_list:
            web_driver = WebDriver(drcs_dict, WebDriver_DDL_Path, "drcs_flow", observer)
            web_driver.start_flow()


def create_idrs_dict(df_data: DataFrame):
    """把文件信息转为DRCS"""
    df_new_idrs = get_df_col_value_df(df_data, "status", 0)
    idrs_id_list = get_loc_unique_list(df_new_idrs, "idrs_id")
    idrs_dict_list = []
    for idrs_id in idrs_id_list:
        df_idrs_info = df_new_idrs[df_new_idrs["idrs_id"]==idrs_id ]
        idrs_col_name_list = ["idrs_id", "prj_code", "lot_code", "title",
                              "sys_attachment", "file_channel",
                              "doc_channel", "comment"]
        idrs_df: DataFrame = df_idrs_info.loc[:, idrs_col_name_list]
        idrs_dict: dict = idrs_df.iloc[0].to_dict()
        idrs_dict["sys_attachment"] = get_attachment_list(idrs_dict["sys_attachment"])
        idrs_dict_list.append(idrs_dict)

    return idrs_dict_list


def create_idrs_flow(idrs_dict_list, observer=None):
    if idrs_dict_list:
        for idrs_dict in idrs_dict_list:
            idrs_flow(idrs_dict)
